LITPATH := "/home/kohel/literature/PoeEdgarAllan/";
TEXPATH := "/home/kohel/teaching/2002.MATH3024/Solutions/";

function SprintReal(r,n)
    error if r gt 1, "Argument 1 must be at most 1";
    rs := Sprint(r);
    if &or[ "e" eq rs[i] : i in [1..#rs] ] then
	m := Ceiling(-Log(10,r))-1;
	ss := Sprint(r*10^m);
	rs := "0." * &cat[ "0" : i in [1..m] ];
	rs *:= &*[ Strings() | ss[i] : i in [3..#ss] ];
    end if;
    if rs eq "0" then
	rs := "0." * &*[ "0" : i in [1..n] ];
    elif #rs gt n+2 then
	rs := &*[ rs[i] : i in [1..n+2] ];
    end if;
    while #rs lt n+2 do rs *:= "0"; end while;
    return rs;
end function;

function ProbabilityVector(F1,F2,XY);
    i := StringToCode(XY[1])-64;
    j := StringToCode(XY[2])-64;
    return Vector([ RealField(8) | F1[i], F1[j],
	F1[i] eq 0 select 0 else F2[i,j]/F1[i],
        F1[j] eq 0 select 0 else F2[i,j]/F1[j],
	F1[i] eq 0 select 0 else F2[j,i]/F1[i],
  	F1[j] eq 0 select 0 else F2[j,i]/F1[j]]);
end function;

procedure PrintVectorLine(FILE,XY,v,r : Digits := 6)
    SL := "\\";
    CR := "\\\\";
    RR := BaseField(Parent(v));
    vs := [ SprintReal(v[i],Digits) : i in [1..6] ];
    V := "(" * vs[1] * ",\\," * vs[2] * ",\\," * vs[3] * ",\\," *
               vs[4] * ",\\," * vs[5] * ",\\," * vs[6] * ")";
    IP := " & " * SprintReal(r,Digits);
    Puts(FILE, "{\\tt " * XY * "} & " * V * IP * CR);
end procedure;

intrinsic LaTeXFrequencyVectors(X::MonStgElt : 
    FileName := "Default")
    {}
    AZ := [ CodeToString(64+i) : i in [1..26] ];
    AA := [ [ X*Y : X in AZ ] : Y in AZ ];
    LaTeXFrequencyVectors(X,AA);
end intrinsic;

intrinsic LaTeXFrequencyVectors(X::MonStgElt,A::[SeqEnum] :
    Projection := Vector([RealField()|1,1,1,1,1,1]),
    FileName := "Default")
    {}
    require #A ge 1 and Type(Universe(A[1])) eq MonStg and 
        &and[ &and[ #XY eq 2 : XY in SS ] : SS in A ] :
        "Argument 2 must be a sequence of sequences of strings of length 2";
    if FileName eq "Default" then
	FILE := Open(TEXPATH * X * "/" * X * ".tex","w");
    else
	FILE := Open(TEXPATH * FileName * ".tex","w");
    end if;
    CR := "\\\\";
    Puts(FILE,"\\documentclass[11pt]{article}");
    Puts(FILE,"\\setlength{\\textwidth}{15cm}");
    Puts(FILE,"\\begin{document}");
    S := StripEncoding(Read(LITPATH * X * ".txt"));
    F1 := FrequencyDistribution(S);
    F2 := DigraphFrequencyDistribution(S);
    for SS in A do
	Puts(FILE,"$$");
	Puts(FILE,"\\begin{array}{cccccccccccccccc}");
	for XY in SS do
	    v := ProbabilityVector(F1,F2,XY);
	    r := InnerProduct(v,Projection);
	    PrintVectorLine(FILE,XY,v,r);
	end for;
	Puts(FILE,"\\end{array}");
	Puts(FILE,"$$");
    end for;
    Puts(FILE,"\\end{document}");
end intrinsic;

intrinsic LaTeXSortFrequencyVectors(X::MonStgElt,XY::MonStgElt : 
    Max := 16, FileName := "Default")
    {}
    if FileName eq "Default" then
	FILE := Open(TEXPATH * X * "." * XY * ".tex","w");
    else
	FILE := Open(TEXPATH * FileName * "." * XY * ".tex","w");
    end if;
    CR := "\\\\";
    S := StripEncoding(Read(LITPATH * X * ".txt"));
    vects, alpha, projs, u :=
        SortFrequencyVectors(S,XY : Max := Max);
    Puts(FILE,"\\documentclass[11pt]{article}");
    Puts(FILE,"\\setlength{\\textwidth}{15cm}");
    Puts(FILE,"\\begin{document}");
    Puts(FILE,"$$");
    Puts(FILE,"\\begin{array}{cccccccccccccccc}");
    for i in [1..Max] do
	r := InnerProduct(u,vects[i]);
	PrintVectorLine(FILE,alpha[i],vects[i],r);
    end for;
    Puts(FILE,"\\end{array}");
    Puts(FILE,"$$");
    Puts(FILE,"\\end{document}");
end intrinsic;

intrinsic LaTeXSortNearFrequencyVectors(X::MonStgElt,XY::MonStgElt : 
    Max := 16, FileName := "Default")
    {}
    if FileName eq "Default" then
	FILE := Open(TEXPATH * X * "." * XY * ".tex","w");
    else
	FILE := Open(TEXPATH * FileName * "." * XY * ".tex","w");
    end if;
    CR := "\\\\";
    S := StripEncoding(Read(LITPATH * X * ".txt"));
    vects, alpha, projs, u :=
        SortNearFrequencyVectors(S,XY : Max := Max);
    Puts(FILE,"\\documentclass[11pt]{article}");
    Puts(FILE,"\\setlength{\\textwidth}{15cm}");
    Puts(FILE,"\\begin{document}");
    Puts(FILE,"$$");
    Puts(FILE,"\\begin{array}{cccccccccccccccc}");
    for i in [1..Max] do
	r := InnerProduct(u,vects[i]);
	PrintVectorLine(FILE,alpha[i],vects[i],r);
    end for;
    Puts(FILE,"\\end{array}");
    Puts(FILE,"$$");
    Puts(FILE,"\\end{document}");
end intrinsic;

intrinsic LaTeXSortFrequencyVectors(
    X::MonStgElt, A::[SeqEnum], V::[ModTupFldElt] : 
    FileName := "Default", Precision := 8)
    {}
    require #A ge 1 and Type(Universe(A[1])) eq MonStg and 
        &and[ &and[ #XY eq 2 : XY in SS ] : SS in A ] :
        "Argument 2 must be a sequence of sequences of strings of length 2";
    bool, V := CanChangeUniverse(V,VectorSpace(RealField(),6));
    require bool : "Argument 3 must be a sequence of real vectors of length 6";
    if FileName eq "Default" then
	FILE := Open(TEXPATH * X * ".tex","w");
    else
	FILE := Open(TEXPATH * FileName * ".tex","w");
    end if;
    CR := "\\\\";
    S := StripEncoding(Read(LITPATH * X * ".txt"));
    Puts(FILE,"\\documentclass[11pt]{article}");
    Puts(FILE,"\\setlength{\\textwidth}{15cm}");
    Puts(FILE,"\\begin{document}");
    for r in [1..#A] do
	vects, alpha, projs := SortFrequencyVectors(S,A[r],V[r]);
	Puts(FILE,"$$");
	Puts(FILE,"\\begin{array}{cccccccccccccccc}");
	for k in [1..#alpha] do
            PrintVectorLine(FILE,alpha[k],vects[k],projs[k]);
	end for;
	Puts(FILE,"\\end{array}");
	Puts(FILE,"$$");
    end for;
    Puts(FILE,"\\end{document}");
end intrinsic;

intrinsic FrequencyVectors(S::MonStgElt,A::[MonStgElt]
    : Precision := 8) -> SeqEnum
    {}
    require &and[ #XY eq 2 : XY in A ] : 
        "Argument 2 must be a sequence of sequences of strings of length 2";
    F1 := FrequencyDistribution(S : Precision := Precision);
    F2 := DigraphFrequencyDistribution(S : Precision := Precision);
    return [ ProbabilityVector(F1,F2,XY) : XY in A ]; 
end intrinsic;

intrinsic SortFrequencyVectors(S::MonStgElt,A::[MonStgElt],u::ModTupFldElt 
    : Precision := 8) -> SeqEnum
    {}
    require &and[ #XY eq 2 : XY in A ] : 
        "Argument 2 must be a sequence of sequences of strings of length 2";
    bool, u := IsCoercible(VectorSpace(RealField(),6),u);
    require bool : "Argument 3 must be a real vector of length 6";
    F1 := FrequencyDistribution(S : Precision := Precision);
    F2 := DigraphFrequencyDistribution(S : Precision := Precision);
    SQ := [ ProbabilityVector(F1,F2,XY) : XY in A ]; 
    n := #SQ;
    pi := Sym(n)!1;
    projs := [ InnerProduct(u,v) : v in SQ ];
    Sort(~projs,~pi);
    return [ SQ[(n-i)^pi] : i in [0..n-1] ],
           [ A[(n-i)^pi] : i in [0..n-1] ],
           Reverse(projs); 
end intrinsic;

intrinsic SortFrequencyVectors(S::MonStgElt, XY::MonStgElt : 
    Max := 0, Precision := 8) -> SeqEnum
    {}
    print "XY =", XY;
    AA := [ CodeToString(64+i)*CodeToString(64+j) : i, j in [1..26] ];
    F1 := FrequencyDistribution(S : Precision := Precision);
    F2 := DigraphFrequencyDistribution(S : Precision := Precision);
    u := ProbabilityVector(F1,F2,XY);
    print "u =", u;
    vects := [ ProbabilityVector(F1,F2,ZW) : ZW in AA ]; 
    projs := [ InnerProduct(u,v) : v in vects ];
    pi := Sym(#vects)!1;
    Sort(~projs,~pi);
    for i in [0..19] do
	AA[(#AA-i)^pi],
	SprintReal(Norm(vects[(#AA-i)^pi]),6),
	vects[(#AA-i)^pi];
    end for;
    n := Max eq 0 select #AA else Max;
    return [ vects[(n-i)^pi] : i in [0..n-1] ],
        [ AA[(n-i)^pi] : i in [0..n-1] ], Reverse(projs), u; 
end intrinsic;

intrinsic SortNearFrequencyVectors(S::MonStgElt, XY::MonStgElt : 
    Max := 0, Precision := 8) -> SeqEnum
    {}
    AA := [ CodeToString(64+i)*CodeToString(64+j) : i, j in [1..26] ];
    F1 := FrequencyDistribution(S : Precision := Precision);
    F2 := DigraphFrequencyDistribution(S : Precision := Precision);
    u := ProbabilityVector(F1,F2,XY);
    vects := [ ProbabilityVector(F1,F2,ZW) : ZW in AA ]; 
    dists := [ Norm(u-v) : v in vects ];
    pi := Sym(#vects)!1;
    Sort(~dists,~pi);
    n := Max eq 0 select #AA else Max;
    return vects, [ AA[i^pi] : i in [1..n] ], dists, u; 
end intrinsic;

